using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using SpoonCore2.Client;
using SpoonCore2.Service;
using System.IO;

namespace SpoonCore2.Message.Filter
{
	class MessageFilterManager
	{
		private readonly SortedList<int, Type> _infos = new SortedList<int, Type>();
		private readonly SortedList<int, IMessageFilter> _filter = new SortedList<int, IMessageFilter>();

		public MessageFilterManager()
		{
			Init();
		}

		private void Init()
		{
			foreach (Type type in Assembly.GetCallingAssembly().GetTypes())
			{
				foreach (Type interf in type.GetInterfaces())
				{
					if (interf == typeof(IMessageFilterInfo) && !type.IsAbstract && !type.IsInterface) _infos.Add(type.FullName.GetHashCode(), type);
					if (interf == typeof(IMessageFilter) && !type.IsAbstract && !type.IsInterface) Register((IMessageFilter)Activator.CreateInstance(type));
				}
			}
		}

		private void Register(IMessageFilter filter)
		{
			int id = filter.InfoType.FullName.GetHashCode();
			_filter.Add(id, filter);
		}

		public void Decode(IList<IMessageFilterInfo> infos, ref byte[] data)
		{
			foreach (IMessageFilterInfo info in infos)
			{
				int id = info.GetType().FullName.GetHashCode();
				if(_filter.ContainsKey(id)) _filter[id].Decode(info, ref data);
			}
		}

		public void Encode(IList<IMessageFilterInfo> infos, ref byte[] data)
		{
			foreach (IMessageFilterInfo info in infos)
			{
				int id = info.GetType().FullName.GetHashCode();
				if (_filter.ContainsKey(id)) _filter[id].Encode(info, ref data);
			}
		}

		public IList<IMessageFilterInfo> SetBytes(BinaryReader br)
		{
			int count = br.ReadInt32();
			IList<IMessageFilterInfo> res = new List<IMessageFilterInfo>();
			while(count > 0)
			{
				int id = br.ReadInt32();
				if(_infos.ContainsKey(id))
				{
					IMessageFilterInfo tmp = (IMessageFilterInfo) Activator.CreateInstance(_infos[id]);
					tmp.SetBytes(br);
					res.Add(tmp);
				}
				count--;
			}
			return res;
		}

		public void GetBytes(BinaryWriter bw, IList<IMessageFilterInfo> infos)
		{
			bw.Write(infos.Count);
			foreach (IMessageFilterInfo info in infos)
			{
				bw.Write(info.GetType().FullName.GetHashCode());
				info.GetBytes(bw);
			}
		}
	}
}